import grpc
from concurrent import futures

import quote_pb2
import quote_pb2_grpc

# 定义正确的 token
VALID_TOKEN = "secret_token"


class Server(quote_pb2_grpc.QuoteServiceServicer):
    # 重写定义的方法，加上真正的处理逻辑
    def GetQuote(self, request, context):
        # 获取发送来的元数据
        metadata = dict(context.invocation_metadata())
        # 从元数据中提取 token
        token = metadata.get("token")

        # 校验 token
        if token != VALID_TOKEN:
            # 返回错误状态码，使得客户端立即终止对此次请求的处理
            context.set_code(grpc.StatusCode.UNAUTHENTICATED)
            # 给客户端具体的错误原因，一般配合状态码使用
            context.set_details("无效的 token ，拒绝访问")
            # 以下响应实际不会被客户端接收到，因为之前已经设置了状态码以及错误信息
            # 且已经给到了客户端，客户端不会再接收其他的响应，这里只是为了满足 python 的语法需求
            # 当然，也可以不加 return ，但不加的话，最后的 return 会被执行，可能存在一些安全问题，尽管客户端不再接收任何响应，但最好还是加上
            return quote_pb2.QuoteResponse()

        return quote_pb2.QuoteResponse(
            data="life is not just your eye's view, and have potry and far."
        )


def serve():
    # 创建一个 grpc 服务器
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    # 将定义的方法注册到服务器中
    quote_pb2_grpc.add_QuoteServiceServicer_to_server(Server(), server)
    # 设置服务器监听 ip 和 port
    server.add_insecure_port("[::]:50051")
    server.start()
    print("服务器已启动，监听 50051 端口")
    server.wait_for_termination()


if __name__ == "__main__":
    serve()
